#!/usr/bin/ruby

#
# edugrep.rb - Main Class for edugrep.
#

$: << "/usr/lib/ruby/1.8/edugrep/lib"

require 'Automaton'
require 'ParseException'
require 'Matcher'
require 'Optimizer'
require 'ParseOpt'
require 'Util'

begin
  # Parse command line options.
  options = ParseOpt.new(ARGV, "1.1.0")
  options.parsing

  # At least the pattern must be specified, or the program will exit.
  if ARGV[0] == nil
    print("Needed parameters not found.\nUSAGE:\n\t edugrep [options] pattern [source file]\n\n For more info type edugrep -h or man edugrep\n\n")
    exit(1)
  end

  # Fills local variables with values parsed from the command line options.
  pattern = ARGV[0]
  verbose = options.verbose
  pretend = options.pretend
  nooptimize = options.nooptimize
  debug = options.debug

  # If a filename is specified but that file does not exist, the program will exit.
  if ARGV[1] != nil && !File.exist?(ARGV[1])
    print "[ERROR] File '" + ARGV[1] + "' not found.\n"  
    exit(1)
  end

  # Creates the automaton instance and does the first (unoptimized) parsing.
  begin
    automa = Automaton.new(pattern)
    ic = automa.ic
    state1 = automa.state1
    state2 = automa.state2
    first_state = automa.espressione()
  rescue ParseException => ex
    print "[ERROR] " + ex.message + "\n"
    exit(1)
  end

  # If '-v, --verbose' was specified, automaton status data is dumped to stdout.
  if verbose
    print "Automaton status (NOT OPTIMIZED) : \n"
    Util.dump_automaton_status(ic, state1, state2)
    print "Initial state : " + first_state.to_s + "\n\n"
  end

  # If optimization was not disabled with '-n', the optimizer will try to remove
  # all unnecessary states.
  if !nooptimize
    ottimizzazione = Optimizer.new(ic, state1, state2, first_state)
    ottimizzazione.ottimizza 
    ic = ottimizzazione.ic
    state1 = ottimizzazione.state1
    state2 = ottimizzazione.state2
    first_state = ottimizzazione.first_state
  
    # If '-v, --verbose' was specified, automaton status data is dumped to stdout.
    if verbose
      print "Automaton status (OPTIMIZED) : \n"
      Util.dump_automaton_status(ic, state1, state2)
      print "Initial state : " + ottimizzazione.first_state.to_s + "\n\n"
    end
  end

  # Unless '-p, --pretend' was specified, the matching begins here.
  if !pretend

    matcher = Matcher.new(ic, state1, state2, first_state)
    matcher.verbose = verbose
    matcher.debug = debug

    # If a filename was specifed, it will be uses as input for the matcher.
    # Otherwise the program will read data from stdin (useful for piping).
    if ARGV[1] != nil
      file = File.open(ARGV[1]) 
      file.each { |line| puts line if (matcher.ricerca_scan(line) > 0) } 
    else
      $stdin.each { |line| puts line if (matcher.ricerca_scan(line) > 0) }
    end

    # Number of matches found
    num_match = matcher.num_match
    inizio = matcher.inizio
    fine = matcher.fine

    # If '-v, --verbose' was specified, the number of matches is printed on stdout.
    if verbose 
      if num_match == 0 then
        print "\nNo match was found\n"
      else
        print "\nFound "+ num_match.to_s + " match(es)\n"
      end
    end

    # Everything went fine!
    exit(0)
  end

rescue => ex
  if verbose
    print "[ERROR] Unexpected error, full stack trace follows:\n\n"
    print ex.message + "\n"
    print ex.backtrace.inspect + "\n"
  else
    print "[ERROR] Unexpected error, specify -v or --verbose to see full stack trace.\n"
  end
  
  exit(1)
end